package cn.study.synchronizedTest;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.openjdk.jol.info.ClassLayout;
/**
 * @Author     ：跟大佳一起学架构
 * @Description：偏向锁 相关测试点
 */
@Slf4j
public class BiasedLockTestDemo {


    /**
     * @description:1、偏向锁延迟偏向
     * @return void
     */
    @Test
    public void biasedLock1() throws InterruptedException {
        log.info(ClassLayout.parseInstance(new Object()).toPrintable());
        Object o = new Object();
        Thread.sleep(4100);
        log.info(ClassLayout.parseInstance(new Object()).toPrintable());
        log.info(ClassLayout.parseInstance(o).toPrintable());
    }


    /**
     * @description:2、偏向锁匿名偏向状态 与 偏向锁
     * @return void
     */
    @Test
    public void biasedLock2() throws InterruptedException {
        Thread.sleep(4100);
        Object obj = new Object();

        log.info(ClassLayout.parseInstance(obj).toPrintable());
        synchronized (obj){
            // 偏向锁
            log.info(ClassLayout.parseInstance(obj).toPrintable());
            // 演示3、再次加锁
            synchronized (obj){
                // 仍为偏向锁
                log.info(ClassLayout.parseInstance(obj).toPrintable());
            }
        }
    }

    /**
     * @description:3、锁类对象
     * @return void
     */
    @Test
    public void biasedLock3() throws InterruptedException {
        log.info(ClassLayout.parseInstance(BiasedLockTestDemo.class).toPrintable());
        Thread.sleep(4100);
        synchronized (BiasedLockTestDemo.class){
            // 偏向锁
            log.info(ClassLayout.parseInstance(BiasedLockTestDemo.class).toPrintable());
        }
    }


    /**
     * @description:4.1、hashcode  偏向锁撤销-无锁或者轻量级锁
     * @return void
     */
    @Test
    public void biasedLock41() throws InterruptedException {
        Thread.sleep(4100);
        Object obj = new Object();
        // 思考： 如果对象调用了hashCode,还会开启偏向锁模式吗
        log.debug(ClassLayout.parseInstance(obj).toPrintable());
        obj.hashCode();
        log.debug(ClassLayout.parseInstance(obj).toPrintable());
        synchronized (obj){
            log.debug(ClassLayout.parseInstance(obj).toPrintable());
        }
    }

    /**
     * @description:4.2、hashcode  偏向锁撤销-重量级锁
     * @return void
     */
    @Test
    public void biasedLock42() throws InterruptedException {
        Thread.sleep(4100);
        Object obj = new Object();
        // 思考： 如果对象调用了hashCode,还会开启偏向锁模式吗
        log.debug(ClassLayout.parseInstance(obj).toPrintable());
        synchronized (obj){
            log.debug(ClassLayout.parseInstance(obj).toPrintable());
            obj.hashCode();
            log.debug(ClassLayout.parseInstance(obj).toPrintable());
        }
    }

    /**
     * @description:5、hashcode  偏向锁撤销-重量级锁
     * @return void
     */
    @Test
    public void biasedLock5() throws InterruptedException {
        Thread.sleep(4100);
        Object obj = new Object();
        // 思考： 如果对象调用了hashCode,还会开启偏向锁模式吗
        log.debug(ClassLayout.parseInstance(obj).toPrintable());

//        synchronized (obj){
//            log.debug(ClassLayout.parseInstance(obj).toPrintable());
//            obj.notify();
//            log.debug(ClassLayout.parseInstance(obj).toPrintable());
//        }
        synchronized (obj){
            log.debug(ClassLayout.parseInstance(obj).toPrintable());
            // wait只能运行在Synchronized下
            obj.wait(10);
            log.debug(ClassLayout.parseInstance(obj).toPrintable());
        }

    }


    /**
     * @description:5、hashcode  为什么要偏向锁撤销
     * @return void
     */
    @Test
    public void biasedLock6() throws InterruptedException {

        Thread.sleep(4100);
        Object obj = new Object();
        log.debug(ClassLayout.parseInstance(obj).toPrintable());
        new Thread(()->{
            synchronized (obj){
                log.debug(Thread.currentThread().getName() + ClassLayout.parseInstance(obj).toPrintable());
            }
        },"Thread1").start();

        Thread.sleep(1000);
        new Thread(()->{
            synchronized (obj){
                log.debug(Thread.currentThread().getName() + ClassLayout.parseInstance(obj).toPrintable());
            }
        },"Thread2").start();

        Thread.sleep(2000);
        synchronized (obj){
            log.debug(ClassLayout.parseInstance(obj).toPrintable());
        }

    }



}
